Skip to content

Implementation of Dedicated Server in Isolation#498

Draft
kuwacom wants to merge 40 commits intosmartcmd:mainfrom
kuwacom:feature/dedicated-server
Draft

Implementation of Dedicated Server in Isolation#498
kuwacom wants to merge 40 commits intosmartcmd:mainfrom
kuwacom:feature/dedicated-server

Conversation

@kuwacom
Copy link
Contributor

@kuwacom kuwacom commented Mar 4, 2026

Description

This PR introduces a Windows64 dedicated server executable (Minecraft.Server) and expands the dedicated-server runtime/build pipeline.

Compared to the initial pull request description, the following features have been newly added:

  • interactive server console (linenoise + command completion),
  • broader server.properties support (including LAN advertise and host options),
  • world bootstrap/load behavior based on level-id,
  • Docker (Wine) runtime support and helper scripts.

Minecraft.Client changes remain focused on dedicated-server bridge compatibility.
#65

image

Changes

Dedicated Server Executable / Startup

  • Added dedicated server entrypoint and project:
    • Minecraft.Server/Windows64/ServerMain.cpp
    • Minecraft.Server/Minecraft.Server.vcxproj (+ filters)
  • Dedicated startup flow now:
    • loads server.properties defaults,
    • applies CLI overrides,
    • bootstraps world by level-id / level-name,
    • performs initial save for newly created worlds,
    • runs periodic autosave and graceful shutdown save.
  • Dedicated launch options:
    • -port, -ip/-bind, -name, -maxplayers, -seed, -loglevel, -help
    • Since the arguments can basically override server.properties, it can also be integrated into fully autonomous deployment systems like Kubernetes.

Dedicated Runtime Modules

  • Added/expanded:
    • ServerProperties (defaulting, normalization, persistence for dedicated options)
    • WorldManager (load existing world by level-id, fallback by name, or create new world)
    • ServerLogger (debug|info|warn|error)
  • Added shared server string utility layer:
    • Minecraft.Server/Common/StringUtils
    • used by logger/properties/world/console paths to avoid duplicated conversion/normalize logic.

Interactive Server Console

  • Added console runtime:
    • ServerCli, ServerCliInput, ServerCliParser, ServerCliEngine, ServerCliRegistry
    • linenoise-based input/history/completion support.
  • Added built-in commands:
    • help (?)
    • stop
    • list
    • tp (teleport)
    • gamemode (gm)
  • Added completion behavior:
    • command/alias completion,
    • player name completion,
    • gamemode token completion (survival|creative|s|c|0|1).

Minecraft.Client Bridge Changes (Dedicated Compatibility Scope)

Only dedicated-server compatibility behavior was changed in client networking paths:

  1. Minecraft.Client/MinecraftServer.h

    • Added NetworkGameInitData::dedicatedNoLocalHostPlayer.
  2. Minecraft.Client/Common/Network/GameNetworkManager.cpp

    • Added dedicated host path to skip local host ClientConnection creation.
    • Preserved host telemetry and multiplayer mode initialization behavior.
  3. Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp

    • Dedicated host startup now uses configured bind IP/port globals.
    • LAN advertising is now controlled by dedicated config (lan-advertise).
  4. Minecraft.Client/Windows64/Network/WinsockNetLayer.h/.cpp

    • Added dedicated LAN advertise global.
    • In dedicated mode, LAN discovery thread is not started.

Build / Tooling / Docs

  • Added CMake target and wiring:
    • CMakeLists.txt: MinecraftServer target + post-build asset copy
    • cmake/CopyServerAssets.cmake: minimal dedicated runtime asset copy
  • Updated solution/docs/ignore:
    • MinecraftConsoles.sln
    • COMPILE.md
    • .gitignore
  • Added Docker runtime support (Wine):
    • docker/dedicated-server/Dockerfile
    • docker/dedicated-server/entrypoint.sh
    • docker-compose.dedicated-server.yml
    • docker-build-dedicated-server.sh
    • start-dedicated-server.sh
    • README.md dedicated Docker section

kuwacom added 4 commits March 4, 2026 18:12
- Introduced `ServerMain.cpp` for the dedicated server logic, handling command-line arguments, server initialization, and network management.
- Created `postbuild_server.ps1` script for post-build tasks, including copying necessary resources and DLLs for the dedicated server.
- Added `CopyServerAssets.cmake` to manage the copying of server assets during the build process, ensuring required files are available for the dedicated server.
- Defined project filters in `Minecraft.Server.vcxproj.filters` for better organization of server-related files.
- Introduced ServerLogger for logging startup steps and world I/O operations.
- Implemented ServerProperties for loading and saving server configuration from `server.properties`.
- Added WorldManager to handle world loading and creation based on server properties.
- Updated ServerMain to integrate server properties loading and world management.
- Enhanced project files to include new source and header files for the server components.
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 4, 2026

I hadn’t been merging upstream changes while implementing, so I’m in the middle of merging them now...

# Conflicts:
#	Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
#	Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp
#	Minecraft.Client/Windows64/Network/WinsockNetLayer.h
@gizmogoat
Copy link

gizmogoat commented Mar 4, 2026

Some things have changed in the past day-ish, watch out for incompatibilities/redundant re-implementations of these:

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 4, 2026

So -server has been added, I see.
From a quick look at the issues, it seems there are still a few world-related bugs remaining.

servers.txt is a nice addition as well.
It’s more user-friendly than -target.

kuwacom added 2 commits March 5, 2026 09:38
Since 31881af56936aeef38ff322b975fd0 , `skinHud.swf` for 720 is not included in `MediaWindows64.arc`,
the app crashes unless the virtual screen is set to HD.
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

It was partially affected by #495, but I was able to merge it without any issues.

@haychk
Copy link

haychk commented Mar 5, 2026

is it still only LAN multiplayer only? or can worlds be opened up to more people?

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

It can be accessed from anywhere if you have a suitable network that can be accessed from the global internet (a network line that can open the specified TCP port).

In short, it's a regular server app.

@haychk
Copy link

haychk commented Mar 5, 2026

oh damn. so i could run this on a vps?

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

Yes, but since it still uses a lot of Windows API internally (to maintain compatibility), it requires a Windows system or a system that includes Windows API to run.

I would like to eventually release a Linux version and put it into Docker.

@haychk
Copy link

haychk commented Mar 5, 2026

i mean, i've tried it on linux and it works fine. i could try and create a docker image if you'd like

@gizmogoat
Copy link

I would like to eventually release a Linux version and put it into Docker.

You can run it fine on Linux without a GUI launcher via umu

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

i mean, i've tried it on linux and it works fine. i could try and create a docker image if you'd like

seriously!
That's nice.

@haychk
Copy link

haychk commented Mar 5, 2026

wine also works really well. tried lutris and has similar results to umu

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

Which one has a smaller image size?
wine or umu

@haychk
Copy link

haychk commented Mar 5, 2026

wine iirc

@void2012 void2012 marked this pull request as draft March 5, 2026 07:45
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

Currently there are two approaches: the separated version (this pull request) and the -server option version (merged yesterday) that starts the client directly as a server. Which one should be prioritized?

The separated version modifies the world-saving logic and changes the startup logic, so integrating it into the client side would be a bit tricky.

Alternatively, it would also be possible to keep both.

@codeHusky
Copy link
Collaborator

Realistically speaking a completely separate Server executable should be our preferred way for this to work. The -server command line option is moreso jank and this is far cleaner.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

If we're planning to merge the separated server in the future, I was considering removing the -server option and the unnecessary client-side logic as well. Would it be okay to leave them as they are for now?

@smartcmd
Copy link
Owner

smartcmd commented Mar 5, 2026

If we're planning to merge the separated server in the future, I was considering removing the -server option and the unnecessary client-side logic as well. Would it be okay to leave them as they are for now?

Yeah

@haychk
Copy link

haychk commented Mar 6, 2026

seems to be a bug where i cannot change the game's difficulty and enable some settings (trust players, pvp etc)
image
image
doing this all on a vps too

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 6, 2026

Sorry, that’s not written in the description, but it’s still a dummy for now.
It’s only included in the default server.properties generation ahead of time (so it can be implemented later).

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 6, 2026

doing this all on a vps too

Would it be possible to send the Dockerfile and docker-compose.yml?

@haychk
Copy link

haychk commented Mar 6, 2026

doing this all on a vps too

Would it be possible to send the Dockerfile and docker-compose.yml?

not using a docker image, which is surprising. i took your pr build and ran it on my vps. works REALLY well, minus the default server settings being awful (peaceful mode, no pvp etc)

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

@hw2007

If shutdown save timed out occurs, isn’t the data just before the server shutdown saved? In the current logic, several save operations are performed during exit.

I found the cause!
The stop command was implemented rather hastily, so it immediately called MinecraftServer::HaltServer();. As a result, the required shutdown processes never finished and it ended up waiting indefinitely.

@goshavindtburg
Copy link

log.txt
Here's the log showing the server hitting the wait thread loop, it doesn't show the cause sadly.

add dedicated server shutdown request handling
@kuwacom kuwacom force-pushed the feature/dedicated-server branch from a0f564f to 590241c Compare March 8, 2026 09:23
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

It looks like something interesting has started in a pull request on my fork.
they’re planning to integrate a plugin system using Lua and C# into this separated Dedicated Server.

sylvessa:feature/dedicated-server

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

log.txt Here's the log showing the server hitting the wait thread loop, it doesn't show the cause sadly.

Did this happen when there was a lot of log output?
@goshavindtburg

@goshavindtburg
Copy link

Got a new log, this time I got a proper log output.
log (1).txt
[2026-03-08 06:05:01.559][DEBUG][client] [app] Trying to write to network, but the socketPlayer is NULL

Removed redundant repeated saves and eliminated the risks of async writes.
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

Got a new log, this time I got a proper log output. log (1).txt [2026-03-08 06:05:01.559][DEBUG][client] [app] Trying to write to network, but the socketPlayer is NULL

Did the server hang at the point where the last log was printed?

Also, please be careful since the IP address is visible in the logs.

@goshavindtburg
Copy link

Got a new log, this time I got a proper log output. log (1).txt [2026-03-08 06:05:01.559][DEBUG][client] [app] Trying to write to network, but the socketPlayer is NULL

Did the server hang at the point where the last log was printed?

Also, please be careful since the IP address is visible in the logs.

The server hangs on the client's end when the socketPlayer stuff gets spammed, but I was able to close the server down and get it to save, which most of the time I can't.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

This packet null error has existed for a while and also occurred in multiplayer on the client.
It might be a good idea to fix these here as well.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

Most of the features have been added.
I’ll add whitelist if I feel like it.

I’ll be on a business trip for work starting tomorrow, so my responses will likely be very slow for a while.

@smartcmd
Copy link
Owner

smartcmd commented Mar 8, 2026

What's the current status of this PR? c:

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

What's the current status of this PR? c:

The basic functionality (what you would want from a multiplayer server) is now in place at a minimum level.
It might be a good idea to merge it once and see how it goes.

Most multiplayer issues that appear later will likely originate from the client implementation, so it might be better to handle those fixes separately from this pull request.
As for adding new features, I’d like to continue doing that within this pull request.

@uncreativeCultist
Copy link

uncreativeCultist commented Mar 8, 2026

i'm a little confused, where do worlds get stored? the server seems to autosave but... not save anything?

nevermind, you have to create the Windows64/GameHDD directory manually.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

i'm a little confused, where do worlds get stored? the server seems to autosave but... not save anything?

nevermind, you have to create the Windows64/GameHDD directory manually.

Changed it so that GameHDD is automatically created if it does not exist.

ZomkaDEV added a commit to ZomkaDEV/MinecraftConsoles that referenced this pull request Mar 8, 2026
@codeHusky
Copy link
Collaborator

If this is functional even with a few caveats I think we'd be okay to merge it in. Would rather have this be something everyone can help you with easily on main than leave you dangling in this PR for longer than needed if that's something you'd prefer. Otherwise no rush, we can wait for you to be ready.

@goshavindtburg
Copy link

When running this under Docker, how do I invoke commands to the server such as ban-ip? or is that impossible

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 10, 2026

When running this under Docker, how do I invoke commands to the server such as ban-ip? or is that impossible

By default std in is disabled so you need to enable it.
After starting with options, you need to specify the service and attach it.

tty: true
stdin_open: true

We'll commit these as defaults later.

@eff3ry
Copy link

eff3ry commented Mar 10, 2026

i got a question about the server console commands, you've created new commands and such but i can also see inside MinecraftServer.cpp alot of existing/old commands?, like time, these arent currently connected to the terminal?

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 10, 2026

i got a question about the server console commands, you've created new commands and such but i can also see inside MinecraftServer.cpp alot of existing/old commands?, like time, these arent currently connected to the terminal?

Even though the function is available, I cannot use it because I have not registered it.
More will be added in the future!

@codeHusky
Copy link
Collaborator

Is there any reason for CLI specific commands rather than a unified command implementation? Bukkit/Paper/JE uses the concept of a CommandSender which can be the console or a player, and iirc there’s some base code in the project that could be used to accomplish something like that. It’d be better for maintainability to only have one set of commands if we can help it

@eff3ry
Copy link

eff3ry commented Mar 10, 2026

please add a server properties setting that parses the world width into here
image
param->xzSize = 5*64; is chunk width
hell scale should be 8 for these large worlds

this value only effects newly generated worlds
Current limit seems to be 5*64 chunks hardcoded inside ChunkSource.h

large worlds seem like mostly ocean past the 54 chunk mark, im thinking theres another setting somewhere

@eff3ry
Copy link

eff3ry commented Mar 10, 2026

To share my findings with server World size,
To set the size of newly generated words we can define that inside the current ServerMain.cpp here:

NetworkGameInitData *param = new NetworkGameInitData();
if (config.hasSeed)
{
	param->seed = config.seed;
}

+> //Set World Size For new Worlds
+> param->xzSize = 5*64; //(5*64);
+> param->hellScale = HELL_LEVEL_SCALE_LARGE;

param->saveData = worldBootstrap.saveData;
param->settings = app.GetGameHostOption(eGameHostOption_All);
param->dedicatedNoLocalHostPlayer = true;

LogStartupStep("starting hosted network game thread");
g_NetworkManager.HostGame(0, true, false, (unsigned char)config.maxPlayers, 0);
g_NetworkManager.FakeLocalPlayerJoined();

We can also expand small worlds already generated by setting some app options, also inside ServerMain.cpp:

app.SetGameHostOption(eGameHostOption_DoMobLoot, serverProperties.doMobLoot ? 1 : 0);
app.SetGameHostOption(eGameHostOption_DoTileDrops, serverProperties.doTileDrops ? 1 : 0);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, serverProperties.naturalRegeneration ? 1 : 0);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, serverProperties.doDaylightCycle ? 1 : 0);


+> //Upgrade World Size
+> app.SetGameNewWorldSize(64*5, true);
+> app.SetGameNewHellScale(HELL_LEVEL_SCALE_LARGE);

StorageManager.SetSaveDisabled(serverProperties.disableSaving);
// Read world name and fixed save-id from server.properties
// Delegate load-vs-create decision to WorldManager

Currently worlds beyond 64*5 chunks wide cannot be created because of a hardcoded limit inside ChunkSource.h
i think if we just bump this #define LEVEL_MAX_WIDTH (5*64) //(6*54) we can increase the world size further
Edit: raising the LEVEL_MAX_WIDTH seems to be crashing the server upon launch,

we just need to tie these values into a Dedicated Server Config file now so that we can easily define world sizes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.